package epoch.game.core.distr.service;

import epoch.game.core.actor.Actor;
import epoch.game.core.common.Loggers;
import epoch.game.core.context.Context;
import epoch.game.core.distr.Node;
import epoch.game.core.distr.NodeMessage;
import epoch.game.core.distr.ThreadContext;
import epoch.game.core.distr.call.Call;
import epoch.game.core.message.SysMessageIds;
import epoch.game.core.serialize.StreamWriter;
import epoch.game.core.util.BeanUtil;

/**
 * 代理基类
 * @author will
 * @date 2016年4月18日 下午8:33:39
 */
public abstract class AbstractProxy {
	
	static private Node node;
	
	// 远程目标节点
	public int remoteNodeId;
	// 服务id
	public int servId;
	//调用参数值，当远程服务为多线程模型时，根据该参数可以自定义分配处理线程
	public long callFlag;
	//是否序列化参数：某些参数对象如果在多个服务之间被访问存在多线程问题，请务必克隆参数
	public boolean cloneParams=false;
	
	public AbstractProxy(){
		
	}

	public static void setNode(Node n) {
		node = n;
	}
	/**
	 * 发送方法调用请求
	 * @param methodKey
	 * @param params
	 */
	protected void sendCall(short methodKey, Object[] params) {
		try {
			ThreadContext threadContext = ThreadContext.getCurrent();
			if(remoteNodeId==0){
//				Loggers.COMMON_LOGGER.error("service not config! servId={},statck={}",servId,BeanUtil.getStack());
				//如果当前有监听要去掉
				if (threadContext != null) {
					threadContext.getAndResetCallBackId();
				}else{
					Actor actor = Context.currentActor();
			    	if (actor != null) {
			    		actor.getAndResetCallbackId();
			    	}
				}
				return;
			}
			
			//call可以考虑用对象池进行优化
			Call call = new Call();
			call.fromNodeId = node.getId();
			
			// 如何知道是否注册回调？
			
			call.callFlag = callFlag;
			call.serviceId = servId;
			call.methodKey = methodKey;
			
			//设置调用堆栈信息，便于调试和问题追踪callerInfo
			call.callerInfo = getStackTrace();
			
			if (threadContext != null) {
				call.isActor = false;
				call.fromPortId = threadContext.getId();
				call.callbackId = threadContext.getAndResetCallBackId();
			} else { // 非ServerThread, 认为Actor
				if (!Context.fillCall(call)) {
					call.isActor = false;
					call.fromPortId = 0;
					call.callbackId = 0;
				}
			}
			if (remoteNodeId == call.fromNodeId) {
				// 本地服务直接调用
				if(cloneParams){
					Object[] clonedParams = BeanUtil.deepClone(params);
					call.methodParam = clonedParams;
				}else{
					call.methodParam = params;
				}
				node.addCall(call);
			} else {
				call.methodParam = params;
				StreamWriter writer = new StreamWriter();
				call.writeTo(writer);
				byte[] calldata = writer.array();
				NodeMessage nodeMsg = new NodeMessage();
				nodeMsg.setId(SysMessageIds.rpc_call);
				nodeMsg.setMsgData(calldata);
				if (!node.sendNodeMsg(remoteNodeId, nodeMsg)) {
					Context.tryReturn(call, null);
				}
			}
		} catch (Exception ex) {
			Loggers.COMMON_LOGGER.error(ex, ex);
		}
	}
	
	/**
	 * 获取调用堆栈信息，文件名:行号 调用者函数名
	 * 
	 * @return
	 */
	public static String getStackTrace() {
		StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
		StackTraceElement e = stackTrace[4];
		return new StringBuilder().append(e.getFileName()).append("->")
				.append(e.getMethodName()).append(":")
				.append(e.getLineNumber()).toString();
	}
}
